from django import forms
from django.core.validators import RegexValidator
# RegexValidato 正则校验器
from django_redis import get_redis_connection
from users.models import Users

# 创建手机号的正则校验器
mobile_validator = RegexValidator(r"^1[3-9]\d{9}$", "手机号码格式不正确")
# RegexValidator(正则,错误提示)

# 校验：1.手机:不为空,手机号格式是否正确,手机号是否注册过
# 2.验证码:不为空,与数据库中存入的数据一样  3.uuid:格式正确

class CheckImgCodeForm(forms.Form):
    """check image code：验证图形验证码"""
    # 手机号格式的验证  form表单的单个字段验证
    # validators form提供的校验器里面写校验的格式 error_messages 是错误提示
    mobile = forms.CharField(max_length=11, min_length=11,
                             validators=[mobile_validator, ],
                             error_messages={"min_length": "手机号长度有误",
                                             "max_length": "手机号长度有误",
                                             "required": "手机号不能为空"})
    # 图形验证码的UUID验证
    image_code_id = forms.UUIDField(error_messages={"required": "图片UUID不能为空"})
    # 图形验证码文本的验证
    text = forms.CharField(max_length=4, min_length=4,
                           error_messages={"min_length": "图片验证码长度有误",
                                           "max_length": "图片验证码长度有误",
                                           "required": "图片验证码不能为空"})

    # Cleaning and validating fields that depend on each other
    # 清理和验证相互依赖的字段
    # 单个字段可以进行校验   单个字段使用[ clean_mobile(self) ] 自己定义一个方法
    # 多个字段也可以一起校验  多个字段使用[ clean(self) ]方法 需要重写父类的clean方法

    def clean(self):  # 重写clean方法 多个字段联合校验
        # print(type(self),id(self),6)
        cleaned_data = super().clean() # 继承父类的clean方法 字典类型数据
        # print(type(cleaned_data),id(cleaned_data),7)
        # print(cleaned_data,8)
        # 1、拿到form表单中传递的数据里的值
        mobile_num = cleaned_data.get("mobile")
        image_text = cleaned_data.get("text")
        image_uuid = cleaned_data.get("image_code_id")
        image_text_upper= image_text.upper() # 把获得的用户输入的数据大写
        # print(image_text_upper)
        # 2、判断手机号是否注册
        if Users.objects.filter(mobile=mobile_num).count():
            raise forms.ValidationError("手机号已注册，请重新输入") # 抛出一个错误
        # 3、判断图形验证码
        con_redis = get_redis_connection(alias='verify_codes') # 连接redis数据库
        img_key = "img_{}".format(image_uuid) # 创建保存到redis中图片验证码的键(key)
        # 取出图片验证码
        real_image_code_origin = con_redis.get(img_key) # 拿到数据库中键对应的值
        # 在redis数据库中取出的值 类型是bytes的字符串 需要解码decode
        # print(type(real_image_code_origin),9)
        # print(real_image_code_origin,10)
        real_image_code = real_image_code_origin.decode('utf-8') if real_image_code_origin else None
        # 三目运算 语法糖 数据库取出的图形验证码
        # print(type(real_image_code),11)
        # print(real_image_code,12)
        # 图形文本验证
        if (not real_image_code) or (image_text_upper != real_image_code):
            raise forms.ValidationError("图片验证失败")
        # 检查是否在60s内有发送记录
        sms_flag_fmt = "sms_flag_{}".format(mobile_num).encode('utf-8')
        sms_flag = con_redis.get(sms_flag_fmt)
        if sms_flag:
            raise forms.ValidationError("获取手机短信验证码过于频繁")
        # con_redis.delete(img_key) # 删除redis数据库中的数据






